import axios from "axios";
import * as qs from "qs";
import { Toast } from "teaset";
import { ActivityIndicator } from "react-native";
import React from "react";
import moment from "moment";
import ToastUtil from "../utils/ToastUtil";

const DEFAULT_TIMEOUT = 10 * 1000;
let customKey = null;
let requestIndex = 0;
let cancelRequestMap = {};


const isDev = process.env.NODE_ENV === "development";

const records = [];
const instance = axios.create({
    timeout: DEFAULT_TIMEOUT
});

const responseParser = {
    dataParser: (data) => data.data,
    messageParser: (data) => data.msg,
    dataValidParser: (data) => data.success,
    dataNeedLogin: null,
    loginAction: null,
    codeParser: (data) => data.code
};

let isReview = true;
let retryCount = 0;
// instance.interceptors.request.use((config) => {
//     requestIndex += 1;
//     const currentRequestIndex = requestIndex;
//     if (!config.cancelToken) {
//         config.cancelToken = new axios.CancelToken((cancelExecutor) => {
//             cancelRequestMap[currentRequestIndex] = cancelExecutor
//         });
//         setTimeout(() => {
//             if (cancelRequestMap[currentRequestIndex] instanceof Function) {
//                 cancelRequestMap[currentRequestIndex](ErrorCode.ConnectTimeOut);
//                 cancelRequestMap[currentRequestIndex] = null;
//             }
//         }, DEFAULT_TIMEOUT);
//     }
//     return config;
// }, null);

instance.interceptors.response.use((response) => {

    if (isDev) {
        if (response.request._method === "GET") {
            console.log("请求路径:" + response.config.url);
            console.log("请求参数:", response.config.params);
            console.log("请求响应:", response);
        } else {
            console.log("请求路径:" + response.config.url);
            console.log("请求参数:", response.config.data);
            console.log("请求响应:", response);
        }
    }
    records.push({ date: moment().format("YYYY-MM-DD HH:mm:ss"), config: response.config, data: response.data });
    if (customKey) {
        Toast.hide(customKey);
        customKey = null;
    }
    if (response.data === undefined || response.data === null) {
        return Promise.reject({ message: "服务器故障，请稍后重试" });
    } else {
        // 处理数据
        if (responseParser.dataValidParser(response.data, response.config)) {
            return {
                data: responseParser.dataParser(response.data, response.config),
                result: response.data,
                config: response.config
            };
        } else {
            if (responseParser.dataNeedLogin && responseParser.dataNeedLogin(response.data)) {
                const config = response.config;
                const backoff = new Promise(function(resolve, reject) {
                    if (responseParser.loginAction) {
                        responseParser.loginAction(resolve, reject);
                    }
                });
                backoff.then(function() {
                    return instance(config);
                }).catch(e => {
                    return Promise.reject(e);
                });
                let error = new Error(responseParser.messageParser(response.data));
                error.code = responseParser.codeParser(response.data);
                return Promise.reject(error);
            } else {
                let error = new Error(responseParser.messageParser(response.data));
                error.code = responseParser.codeParser(response.data);
                error.data = responseParser.dataParser(response.data);
                return Promise.reject(error);
            }
        }
    }
}, error => {
    records.push({ date: moment().format("YYYY-MM-DD HH:mm:ss"), config: error.config, error: error });
    if (isDev) {
        if (error.request && error.config) {
            if (error.request._method === "GET") {
                console.log("请求路径:" + error.config.url);
                console.log("请求参数:", error.config.params);
            } else {
                console.log("请求路径:" + error.config.url);
                console.log("请求参数:", error.config.data);
            }
            console.log(error.config.url, error);
        } else {
            console.log(error);
        }
    }
    if (customKey) {
        Toast.hide(customKey);
        customKey = null;
    }
    let code = 0
    try {
        code = error.response.data.status
    } catch (e) {
        if (error.toString().indexOf('Error: timeout') !== -1) {
            return Promise.reject(error)
        }
    }

    let config = error.config;
    if (retryCount > 0) {
        const { __retryCount = 0, retryDelay = 300 } = config;
        // 在请求对象上设置重试次数
        config.__retryCount = __retryCount;
        // 判断是否超过了重试次数
        if (__retryCount < retryCount) {
            console.log('请求失败，自动重试:', __retryCount);
            // 增加重试次数
            config.__retryCount++;
            // 延时处理
            const delay = new Promise((resolve) => {
                setTimeout(() => {
                    resolve();
                }, retryDelay);
            });
            // 重新发起请求
            return delay.then(function () {
                return axios(config);
            });
        }
    }
    if (code) {
        if (code === 401) {

        } else if (code === 403) {

        } else {
            const errorMsg = error.response.data.message
            if (errorMsg !== undefined) {
                error.message = errorMsg;

            }
        }
    } else {
        error.message = '';
    }
    return Promise.reject(error);
});
let g_user = null;

let injections = {};

let g_shared_data = {};

class HttpUtil {
    static uploadCancleToken = null;

    static getAxiosInstance() {
        return instance;
    }

    static get(url, params, hud) {
        if (hud) {
            if (customKey) {
                Toast.hide(customKey);
            }
            customKey = Toast.show({
                    icon: <ActivityIndicator size="large" color={"white"} />,
                    position: "center",
                    duration: 1000000,
                    modal: true
                }
            );
        }
        return instance.get(url, { params: params, paramsSerializer:(p)=> qs.stringify(p, {arrayFormat: 'repeat'}) });
    }

    static do(method, url, params, hud = false) {
        if (method === "POST") {
            return HttpUtil.post(url, params, hud);
        } else if (method === "JSON") {
            return HttpUtil.postJson(url, params, hud);
        } else {
            return HttpUtil.get(url, params, hud);
        }
    }

    static post(url, data, hud) {
        return this.post(url, data, hud, null);
    }

    static postJson(url, data, hud) {
        return this.post(url, data, hud, null, true);
    }

    static post(url, data, hud, config = null, json = false) {
        if (hud) {
            if (customKey) {
                Toast.hide(customKey);
            }
            customKey = Toast.show({
                    icon: <ActivityIndicator size="large" color={"white"} />,
                    position: "center",
                    duration: 1000000,
                    modal: true
                }
            );
        }
        if (config) {
            return instance.post(url, json ? data : qs.stringify(data), config);
        } else {
            return instance.post(url, json ? data : qs.stringify(data));
        }
    }

    static put(url, data, hud) {
        return this.put(url, data, hud, null);
    }

    static putJson(url, data, hud) {
        return this.put(url, data, hud, null, true);
    }

    static put(url, data, hud, config = null, json = false) {
        if (hud) {
            if (customKey) {
                Toast.hide(customKey);
            }
            customKey = Toast.show({
                    icon: <ActivityIndicator size="large" color={"white"} />,
                    position: "center",
                    duration: 1000000,
                    modal: true
                }
            );
        }
        if (config) {
            return instance.put(url, json ? data : qs.stringify(data), config);
        } else {
            return instance.put(url, json ? data : qs.stringify(data));
        }
    }

    static delete(url, data, hud) {
        return this.delete(url, data, hud, null);
    }

    static deleteJson(url, data, hud) {
        return this.delete(url, data, hud, null, true);
    }

    static delete(url, data, hud, config = null, json = false) {
        if (hud) {
            if (customKey) {
                Toast.hide(customKey);
            }
            customKey = Toast.show({
                    icon: <ActivityIndicator size="large" color={"white"} />,
                    position: "center",
                    duration: 1000000,
                    modal: true
                }
            );
        }
        if (config) {
            return instance.delete(url, { ...config, data: json ? data : qs.stringify(data) });
        } else {
            return instance.delete(url, { ...config, data: json ? data : qs.stringify(data) });
        }
    }

    static header(url) {
        return instance.head(url);
    }

    static setUser(user) {
        g_user = user;
    }

    static getUser() {
        return g_user;
    }

    static isLogin() {
        return g_user !== null;
    }

    static upload(url, uri, data, hud, name, key = "file", onUploadProgress = null) {
        let formData = new FormData();// 创建form对象
        const index = uri.lastIndexOf("/");
        let file = { uri: uri, type: "multipart/form-data", name: name || uri.substr(index + 1) };
        formData.append(key, file);
        for (let item in data) {
            formData.append(item, data[item]);
        }
        if (hud) {
            if (customKey) {
                Toast.hide(customKey);
            }
            customKey = Toast.show({
                    icon: <ActivityIndicator size="large" color={"white"} />,
                    position: "center",
                    duration: 1000000,
                    modal: true
                }
            );
        }
        let CancelToken = axios.CancelToken;
        return instance.post(url, formData, {
            headers: {
                "Content-Type": "multipart/form-data"
            },
            onUploadProgress: onUploadProgress,
            cancelToken: new CancelToken(function executor(c) {
                HttpUtil.uploadCancleToken = c;
            }),
            timeout: 60 * 1000 * 10,
            maxContentLength: 1024 * 1024 * 1024
        });
    }

    static cancelUpload() {
        if (HttpUtil.uploadCancleToken) {
            HttpUtil.uploadCancleToken("Upload Cancelled");
            HttpUtil.uploadCancleToken = null;
        }
    }

    static uploadFiles(url, files, data, hud) {
        let formData = new FormData();// 创建form对象
        if (files) {
            for (let i = 0; i < files.length; i++) {
                let file = { uri: files[i].uri, name: files[i].name, type: files[i].type };
                formData.append(files[i].key, file);
            }
        }
        if (data) {
            for (let item in data) {
                formData.append(item, data[item]);
            }
        }
        if (hud) {
            if (customKey) {
                Toast.hide(customKey);
            }
            customKey = Toast.show({
                    icon: <ActivityIndicator size="large" color={"white"} />,
                    position: "center",
                    duration: 1000000,
                    modal: true
                }
            );
        }
        return instance.post(url, formData, {
            headers: {
                "Content-Type": "multipart/form-data"
            }
        });
    }

    static injectApi(name, injection) {
        if (injections[name] || injections[name] === 0) {
            const old = injections[name];
            instance.interceptors.request.eject(old);
        }
        injections[name] = instance.interceptors.request.use((config) => {
            injection && injection(config);
            return config;
        }, null);
    }

    static rejectApi(name) {
        if (injections[name] || injections[name] === 0) {
            const old = injections[name];
            instance.interceptors.request.eject(old);
            injections[name] = null;
        }
    }

    static getNetworkRecords() {
        return records;
    }

    static setItem(key, value) {
        g_shared_data[key] = value;
    }

    static getItem(key, defaultValue) {
        return g_shared_data[key] || defaultValue;
    }

    static review() {
        if (__DEV__) {
            return false;
        }
        return isReview;
    }

    static setReview(review) {
        isReview = review;
    }



    static setResponseDataParser(parser) {
        responseParser.dataParser = parser;
    }

    static setResponseMessageParser(parser) {
        responseParser.messageParser = parser;
    }

    static setResponseDavaValidPraser(parser) {
        responseParser.dataValidParser = parser;
    }

    static setResponseDataNeedLogin(dataNeedLogin) {
        responseParser.dataNeedLogin = dataNeedLogin;
    }

    static setRetryCount(rc) {
        retryCount = rc;
    }

    static setResponseLoginAction(action) {
        responseParser.loginAction = action;
    }

    static setBaseUrl(url) {
        instance.defaults.baseURL = url;
    }

    static getBaseUrl() {
        return instance.defaults.baseURL;
    }
}

export default HttpUtil;
